/*
 * QTXpost - a Qt-based blog client.
 * Copyright (C) 2010 Helen Sommer
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (in COPYING); if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA  02111-1307  USA
 *
 * The project is hosted on http://code.google.com/p/qtxpost
 */

#include "xmlrpcclient.h"
#include "xmlrpcconv.h"
#include "httpclient.h"

#include "MainWindow.h"
#include "Server.h"
#include "Config.h"
#include "SaveFile.h"

extern MainWindow *root;
extern Config *config;

Server::Server(int count, QWidget *parent) 
  : QFrame(parent)
{
  QSqlQuery query;
  QString command;

  initialize();
  command = QString("select id, username, label, server, password, position, hidden, selected, type from users order by position limit %1,1").arg(count);
  query.exec(command);
  if (query.next()) {
    id = query.value(0).toInt();
    username = query.value(1).toString();
    label = query.value(2).toString();
    server = query.value(3).toString();
    password = query.value(4).toString();
    position = query.value(5).toInt();    
    hidden = query.value(6).toBool();
    selected = query.value(7).toBool();
    serverType = query.value(8).toInt(); // 0 - LJ_TYPE; 1 - DW_TYPE

    labelLabel->setText(label);
    communitiesButton->setText(username);
    
    updateIcons();
    changeIcon();
    updateMoods();
    communities->readCommunities();
    communities->readGroups();
    initializeRpc();

    if (hidden)
      hide();
    else if (selected) {
      selectedToggle->setChecked(true);
    }
  }
  else {  // can't happen
    qDebug() << "Error reading database! users table is corrupted.";
    exit(1);
  }
}

Server::Server(QString username_, QString password_, QString label_, QString server_, int serverType_, QWidget *parent) 
  : QFrame(parent)
{
  QSqlQuery query;
  QString command;
  int serverId;

  initialize();

  username = username_;
  password = password_;
  label = label_;
  server = server_;
  serverType = serverType_;

  command = QString("select max(position)+1 as position from users");
  query.exec(command);
  query.next();
  position = query.value(0).toInt();

  // currently not using autoincrement, in order to reuse deleted ids someday
  command = QString("select max(id)+1 as server_id from users");
  query.exec(command);
  query.next();
  serverId = query.value(0).toInt();

  command = QString("insert into users (id, username, password, label, server, position, type) values (%1, \"%2\", \"%3\", \"%4\", \"%5\", %6, %7)").arg(serverId).arg(username).arg(escapeSql(password)).arg(escapeSql(label)).arg(server).arg(position).arg(serverType);
  query.exec(command);
  // id = query.lastInsertId().toInt(); // only for auto increment
  id = serverId;
  
  labelLabel->setText(label);
  communitiesButton->setText(username);
  keywordsCombo->addItem("-----");

  initializeRpc();
}

QString Server::escapeSql(QString string)
{
  QString escaped = string;
  escaped.replace(QRegExp("(\"|'|\\\\)"),"\\\\1");
  return escaped;
}

void Server::initialize()
{
  setupUi(this);

  state = LJ_NONE;
  communities = NULL;
  doUpdateCommunities = false;
  doUpdateGroups = false;
  hidden = false;
  deleted = false;
  selected = false;
  copied = false;
  serverType = LJ_TYPE;
  updateGroupId = 0;
  updateGroupMask = 0;

  icon->setPixmap(QPixmap(":/images/empty.png"));

  connect(keywordsCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changeIcon()));
  connect(communitiesButton, SIGNAL(clicked()), this, SLOT(selectCommunities()));
  connect(selectedToggle, SIGNAL(stateChanged(int)), this, SLOT(selectServer(int)));
  connect(copyToggle, SIGNAL(stateChanged(int)), this, SLOT(copyIconKeyword(int)));
  copyToggle->hide();
  communities = new Communities(this);

  manager = new QNetworkAccessManager();
  connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(finished(QNetworkReply *)));

  identityTypes[""] = IDENTITY_USER;
  identityTypes["community"] = IDENTITY_COMMUNITY;
  identityTypes["syndicated"] = IDENTITY_SYNDICATED;
  identityTypes["news"] = IDENTITY_NEWS;
  identityTypes["shared"] = IDENTITY_SHARED;

}

void Server::initializeRpc()
{
  client = new XmlRpcClient(server, 80);
  connect(client, SIGNAL(dataReady(QVariant)), this, SLOT(clientResponse(QVariant)));
}

QCheckBox* Server::getSelected()
{
  return selectedToggle;
}

void Server::unselect()
{
  selectedToggle->setChecked(false);
  copyToggle->hide();
}

void Server::updatePosition(int position_)
{
  position = position_;
  QSqlQuery query;
  QString command;
  command = QString("update users set position=%1 where id=%2").arg(position).arg(id);
  query.exec(command);
}

void Server::updateIcons()
{
  keywordsCombo->clear();
  keywordsCombo->addItem("-----");

  QSqlQuery query;
  QString command;
  
  if (config->settings["db"] == "sqlite") {
    // force case-insensitive search
    // todo: specify it while creating the table; make a script to copy content from the old table on upgrading
    command = QString("select keyword from keywords where users_id=%1 order by keyword collate nocase").arg(id);    
  }
  else {
    command = QString("select keyword from keywords where users_id=%1 order by keyword").arg(id);   
  }


  query.exec(command);
  while (query.next()) {
   QString keyword = query.value(0).toString();
   keywordsCombo->addItem(keyword);
  }
  changeIcon();
}

void Server::changeIcon()
{
  QString icon_keyword = keywordsCombo->currentText();
  
  changeIcon(icon_keyword);
  if (copyToggle->isChecked())
    root->updateIcons(id,icon_keyword);
}

void Server::changeIcon(QString keyword)
{
  QSqlQuery query;
  QString command;

  if (!keyword.compare("-----")) {
    command = QString("select filename from icons, default_icons where icons.users_id=%1 and default_icons.users_id=%2 and icons_id=id").arg(id).arg(id);
  }
  else {
    command = QString("select filename from keywords, icons where icons.users_id=%1 and keywords.users_id=%2 and icons_id=id and keyword=\"%3\"").arg(id).arg(id).arg(keyword);
  }
  query.exec(command);
  if (query.next()) {
    QString filename = query.value(0).toString();
    icon->setPixmap(QPixmap(filename));
  }
  else
    icon->setPixmap(QPixmap(":/images/empty.png"));
}

void Server::setIconKeyword(QString keyword)
{
  keywordsCombo->setCurrentIndex(keywordsCombo->findText(keyword));
  changeIcon(keyword);
}

void Server::updateMoods()
{
  moods.clear();
  QSqlQuery query;
  QString command = QString("select mood from moods where users_id=%1").arg(id);
  query.exec(command);
  while (query.next()) {
    moods.append(query.value(0).toString());
  }
}

void Server::updateDatabase(QString username, QString password, QString label, QString server, int serverType)
{
  QSqlQuery query;
  QString command;

  command = QString("update users set username=\"%2\", password=\"%3\", label=\"%4\", server=\"%5\", type=\"%6\" where id=\"%1\"").arg(id).arg(username).arg(escapeSql(password)).arg(escapeSql(label)).arg(server).arg(serverType);
  query.exec(command);
  labelLabel->setText(label);
}

void Server::update(QString username_, QString password_, QString label_, QString server_, int serverType_, bool icons, bool force_icons, bool moods)
{
  // always tries to login to server, even if moods and icons are not updated 

  if (server != server_) { // must reinitialize xmlrpc
    delete client;
    server = server_;
    initializeRpc();
  }

  username = username_;
  password = password_;
  label = label_;
  serverType = serverType_;

  updateDatabase(username, password, label, server, serverType);

  doUpdateIcons = icons;
  doForceUpdateIcons = force_icons;
  doUpdateMoods = moods;

  startGetUserData();
}

int Server::getCommunities()
{
  QSqlQuery query;
  QString command;
  
  communityNames.clear();
  command = QString("select community from communities where users_id=%1 and selected=1").arg(id);
  query.exec(command);
  while (query.next()) {
    communityNames.append(query.value(0).toString());
  }
  if (communityNames.size() == 0) { 
    // if nothing is selected, select username
    communityNames.append(username);
  }
  currentCommunity = 0;
  return communityNames.size();
}

int Server::getCommunities(QString community)
{
  QSqlQuery query;
  QString command;
  
  communityNames.clear();
  communityNames.append(community);

  command = QString("update communities set selected=1 where users_id=%1 and comunity=\"%2\"").arg(id).arg(community);
  query.exec(command);
  currentCommunity = 0;
  return communityNames.size();
}

void Server::updateCommunities(QList<QString> communities)
{
  QSqlQuery query;
  QString command;

  command = QString("delete from communities where users_id=%1").arg(id);
  query.exec(command);

  // username is always in the list of communities, with type=1
  command = QString("insert into communities (community,users_id,type) values (\"%1\",%2,1)").arg(username).arg(id);
  query.exec(command);

  for (int i = 0; i < communities.size(); i++) {
    if (communities.at(i) != username) {
      command = QString("insert into communities (community,users_id) values (\"%1\",%2)").arg(communities.at(i)).arg(id);
      query.exec(command);
    }
  }
}

void Server::updateGroups(QList<QMap < QString, QVariant> > groups, int type)
// type = 0: trustgroups (DW), friendgroups (LJ)
// type = 1: content filters (DW)
{
  QSqlQuery query;
  QString command;

  command = QString("delete from groups where users_id=%1 and type=%2").arg(id).arg(type);
  query.exec(command);

  for (int i = 0; i < groups.size(); i++) {
    QMap<QString,QVariant> group = groups.at(i);
    if (type == 0) {
      command = QString("insert into groups (users_id, name, bit, sortorder, public, type) values (%1, \"%2\", %3, %4, %5, %6)").arg(id).arg(group["name"].toString()).arg(group["id"].toInt()).arg(group["sortorder"].toInt()).arg(group["public"].toInt()).arg(type);
    }
    else {
      command = QString("insert into groups (users_id, name, bit, sortorder, public, type, data) values (%1, \"%2\", %3, %4, %5, %6, \"%7\")").arg(id).arg(group["name"].toString()).arg(group["id"].toInt()).arg(group["sortorder"].toInt()).arg(group["public"].toInt()).arg(type).arg(group["data"].toString());
    }
    query.exec(command);
  }
}

void Server::updateMoods(QHash<int,QString> moods_)
{
  QSqlQuery query;
  QString command;

  command = QString("delete from moods where users_id=%1").arg(id);
  query.exec(command);
  moods.clear();

  QHashIterator<int, QString> i(moods_);
  while (i.hasNext()) {
    i.next();
    command = QString("insert into moods (id,mood,users_id) values (%1,\"%2\",%3)").arg(i.key()).arg(i.value()).arg(id);
    query.exec(command);
    moods.append(i.value());
  }
  root->updateMoods();
}

void Server::updateIcons(QList<QString> urls, QList<QString> keywords)
// update user icons from the server (after login)
{
  int iconId;
  QSqlQuery query;
  QString url,command,filename;
  
  QString icons_dir = QString("%1/%2/icons/").arg(config->configDirectory).arg(id);
  QDir dir(icons_dir);
  if (!dir.exists(icons_dir)) {
    if (!dir.mkpath(icons_dir)) {
      qDebug() << "Error: can't create icons directory! " << icons_dir;
    }
  }

  if (doForceUpdateIcons) {
    command = QString("delete from icons where users_id=%1").arg(id);
    query.exec(command);
    dir.setFilter(QDir::Files | QDir::NoSymLinks);
    QFileInfoList list = dir.entryInfoList();
    QFile file;
    QFileInfo file_info;
    for (int i = 0; i < list.size(); i++) {
      file_info = list.at(i);
      file.setFileName(QString(icons_dir).append(file_info.fileName()));
      file.remove();
    }
  }

  QHash<QString,int> distinct; // distinct icon urls (several keywords can correspond to one icon)
  download.clear();
  for (int i = 0; i < urls.size(); i++) {
    url = urls.at(i);
    if (distinct.contains(url)) continue;
    command = QString("select id,filename from icons where users_id=%1 and picurl=\"%2\"").arg(id).arg(url);
    query.exec(command);
    if (query.next()) {
      iconId = query.value(0).toInt();      
      filename = query.value(1).toString();     
      if (QFile::exists(filename)) {
        distinct[url] = iconId; // icon already exists - do not download
        continue;
      }
    }

    // if we get here, the icon must be downloaded
    QString numbers = QString(url);
    numbers.replace(QRegExp("\\D"),""); 
    // select only digits from the url to create the icon filename
    // (must be unique)
    
    filename = QString("%1/%2/icons/%3").arg(config->configDirectory).arg(id).arg(numbers);
    command = QString("insert into icons (users_id, picurl, filename) values (%1,\"%2\",\"%3\")").arg(id).arg(url).arg(filename);
    query.exec(command);
    if (query.lastError().isValid()) { // shouldn't happen
      qDebug() << query.lastError().driverText() << "   " << query.lastError().databaseText();
    }
    
    iconId = query.lastInsertId().toInt();
    distinct[url] = iconId;       
    download.append(url);
  }

  // update icon keywords
  command = QString("delete from keywords where users_id=%1").arg(id);
  query.exec(command);
  
  for (int i = 0; i < keywords.size(); i++) {
    if (!distinct.contains(urls.at(i))) {
      qDebug() << "Unexpected error while updating icon keywords.";
    }
    else {
      iconId = distinct.value(urls.at(i));
      command = QString("insert into keywords (users_id,icons_id,keyword) values (%1,%2,\"%3\")").arg(id).arg(iconId).arg(keywords.at(i));
      query.exec(command);
      if (query.lastError().isValid()) {
        qDebug() << query.lastError().driverText() << "   " << query.lastError().databaseText();
      }
    }
  }
  
  // delete old icons which were removed from the server
  QList<int> toDelete;
  command = QString("select picurl,id from icons where users_id=%1").arg(id);
  query.exec(command);
  while (query.next()) {
    url = query.value(0).toString();
    if (!distinct.contains(url)) {
      toDelete.append(query.value(1).toInt());
    }
  }
  // LATER - make it one command
  for (int i = 0; i < toDelete.size(); i++) {
    command = QString("delete from icons where id=%1").arg(toDelete.at(i));
    query.exec(command);
  }

  //update default icon
  if (defaultIconUrl != "") {
    command = QString("select id from icons where users_id=%1 and picurl=\"%2\"").arg(id).arg(defaultIconUrl);
    query.exec(command);
    query.next(); // must exist
    iconId = query.value(0).toInt(); 
    command = QString("replace into default_icons (users_id,icons_id) values (%1,%2)").arg(id).arg(iconId);
    query.exec(command);
  }

  // download new icons, if there's something to download
  if (!download.isEmpty()) {
    downloadTarget = download.size();
    downloadCount = 0;
    root->serverConfig->initializeProgress(downloadTarget);
    
    // delay between downloading icons, to avoid hitting the server with multiple requests at once
    for (int i = 0; i < downloadTarget; i++) {
      int delay = i*10;
      QTimer::singleShot(delay, this, SLOT(downloadStart()));
    }
  }
  else {
    updateIcons();
    root->serverConfig->completeProgress();
  }
}

void Server::downloadStart()
{
  if (download.isEmpty()) return;
  QUrl url(download.at(0));
  download.remove(0);
  qDebug() << "downloading url=" << url;
  QNetworkRequest request(url);
  manager->get(QNetworkRequest(url));
}

void Server::downloadFinished()
{
  root->serverConfig->incrementProgress();
  downloadCount++;
  if (downloadCount == downloadTarget) {
    updateIcons();
  }
  qDebug() << "downloadFinished: count=" << downloadCount << " target=" << downloadTarget;
}

void Server::selectCommunities()
{
  if (communities == 0) {
    communities = new Communities(this);
  }
  else if (doUpdateCommunities) {
    communities->updateCommunities();
    communities->updateGroups();
  }
  else if (doUpdateGroups) {
    communities->updateGroups();
  }
  doUpdateCommunities = doUpdateGroups = false;
  communities->show();
}

void Server::renameCommunitiesButton(QString title)
{
  communitiesButton->setText(title);
}

void Server::deleteServer()
{
  QSqlQuery query;
  QString command;

  deleted = true;
  hide();
  
  command = QString("select filename from icons where users_id=%1").arg(id);
  query.exec(command);
  while (query.next()) {
    QString filename = query.value(0).toString();
    QFile::remove(filename);
  }

  for (int i = 0; i < config->tables.size(); i++) {
    if (config->tables.at(i) != "users") {
      command = QString("delete from %2 where users_id=%1").arg(id).arg(config->tables.at(i));
      query.exec(command);
    }
  }
  command = QString("delete from users where id=%1").arg(id);
  query.exec(command);
}

void Server::hideServer(bool doHide)
{
  hidden = doHide;
  if (hidden)
    hide();
  else 
    show();
  QSqlQuery query;
  QString command = QString("update users set hidden=%1 where id=%2").arg(hidden).arg(id);
  query.exec(command);
}

void Server::selectServer(int selected_)
{
  selected = selected_;

  if (root != 0) { // otherwise it's still initialization, root is not ready yet
    root->displayMoods();

    QSqlQuery query;
    QString command = QString("update users set selected=%1 where id=%2").arg(selected).arg(id);
    query.exec(command);
  }
  if (selected) {
    copyToggle->show();
  }
  else {
    disableCopyIconKeyword();
    copyToggle->hide();
  }
}

void Server::disableCopyIconKeyword()
{
  copied = false;
  copyToggle->setChecked(false);
}

void Server::copyIconKeyword(int doCopy)
{
  if (!doCopy) {
    copied = false;
  }
  else {
    copied = true;
    QString icon_keyword = keywordsCombo->currentText();
    root->updateIcons(id, icon_keyword);
  }
}

bool Server::eventInSync(QString subject, QDateTime date, QString &message)
{
  inSync = true;
  int diff = abs(lastDate.secsTo(date));
  // qDebug() << "eventInSync for " << label << " subject=" << subject << " date=" << date << " lastSubject=" << lastSubject << " lastDate=" << lastDate << " diff=" << diff;
  if ((subject != lastSubject) || (diff > 180)) { 
    // event is not in sync: either subject is different, or posting time differs by more than 3 min
    message = QString("\n[%1: %2]").arg(lastDate.toString("yyyy-MM-dd HH:mm")).arg(lastSubject);
    inSync = false;
  }
  // qDebug() << "inSync" << inSync;
  return inSync;
}

void Server::finished(QNetworkReply *reply)
{
  QUrl url = reply->url();
  if (reply->error()) {
    qDebug() << "Download of " << url << " failed: " << reply->errorString();
  } 
  else {
    QString numbers = QString(url.toString());
    numbers.replace(QRegExp("\\D"),""); 
    // select only digits from the url to create the icon filename
    // (must be unique)
    
    QString filename = QString("%1/%2/icons/%3").arg(config->configDirectory).arg(id).arg(numbers);
    SaveFile *saveFile = new SaveFile(reply, filename);
    connect (saveFile, SIGNAL(ready()), this, SLOT(downloadFinished()));
    saveFile->start(QThread::LowPriority);
  }
}

void Server::updateFriends(QHash<QString, QMap < QString, QVariant> > friends, QMultiHash<QString, QString> flags)
{
  QSqlQuery query;
  QString command;

  QHash<QString,int> communities;
  command = QString("select community from communities where users_id=%1 and type=0").arg(id);
  query.exec(command);
  while (query.next()) {
    communities.insert(query.value(0).toString(), 1);
  }
  command = QString("delete from friends where users_id=%1").arg(id);
  query.exec(command);
  QHashIterator <QString, QMap <QString, QVariant> > i(friends);
  while (i.hasNext()) {
    i.next();
    QString username = i.key();
    QMap <QString, QVariant> user = i.value();
    
    QString fullname = QString::fromUtf8(user["fullname"].toString().toAscii().data()); 
    QString birthday = user["birthday"].toString();
    QString fgcolor = user["fgcolor"].toString();
    QString bgcolor = user["bgcolor"].toString();
    QString stype = user["type"].toString();

    int type = 0;
    if (identityTypes.contains(stype)) {
      type = identityTypes.value(stype);
    }

    qulonglong mask = user["groupmask"].toULongLong();
    int trust = (flags.contains(username, "trust")) ? 1 : 0;
    int trusted = (flags.contains(username, "trusted")) ? 1 : 0;
    int watch = (flags.contains(username, "watch")) ? 1 : 0;
    int watched = (flags.contains(username, "watched")) ? 1 : 0;

    if (type != 0) {
      if (serverType == LJ_TYPE) { // flags are returned differently
        watch = trust; 
        trust = trusted;
        watched = trusted = 0;
      }
      if (type == 1 && communities.contains(username)) {
        trust = 1;
        communities.remove(username);
      }
    }

    // todo: add 'status' key (for deleted users on LJ - this key is set to "purged")

    command = QString("insert into friends (users_id, username, fullname, type, mask, trust, trusted, watch, watched, birthday, fgcolor, bgcolor) values (%1, \"%2\", \"%3\", %4, \"%5\", %6, %7, %8, %9, \"%10\", \"%11\", \"%12\")").arg(id).arg(username).arg(fullname).arg(type).arg(mask).arg(trust).arg(trusted).arg(watch).arg(watched).arg(birthday).arg(fgcolor).arg(bgcolor);
    query.exec(command);
  }

  // add the communities to which the user is not subscribed but has posting access
  QHashIterator <QString, int> j(communities);
  while (j.hasNext()) {
    j.next();
    QString community = j.key();
    command = QString("insert into friends (users_id, username, fullname, type, trust) values (%1, \"%2\", \"%3\", 1, 1)").arg(id).arg(community).arg(community);
    query.exec(command);
  }

}

void Server::updateGroup()
{
  QSqlQuery query;
  QString command;
  int sortorder = 50; // default

  switch (updateMode){
  case MODE_ADD_GROUP:
    command = QString("insert into groups (users_id, name, bit, sortorder, type) values (%1, \"%2\", \"%3\", %4, %5)").arg(id).arg(updateGroupName).arg(updateGroupId).arg(sortorder).arg(updateGroupType);
    break;
  case MODE_UPDATE_GROUP:
    if (updateGroupSortOrder >= 0) {
      command = QString("update groups set name=\"%1\", sortorder=%5, public=%6 where users_id=\"%2\" and bit=\"%3\" and type=%4").arg(updateGroupName).arg(id).arg(updateGroupId).arg(updateGroupType).arg(updateGroupSortOrder).arg(updateGroupPublic);
    }
    else {
      command = QString("update groups set name=\"%1\" where users_id=\"%2\" and bit=\"%3\" and type=%4").arg(updateGroupName).arg(id).arg(updateGroupId).arg(updateGroupType);
    }
    break;
  case MODE_DELETE_GROUP:
    command = QString("delete from groups where users_id=%1 and bit=\"%2\" and type=%3").arg(id).arg(updateGroupId).arg(updateGroupType);
    break;
  }

  query.exec(command);
  if (updateGroupType == 0) {
    communities->updateGroups();
  }
  root->friendsManager->updateGroupEnd();
}

void Server::updateUser()
{
  QSqlQuery query;
  QString command;

  command = QString("update friends set mask=\"%1\" where users_id=%2 and username=\"%3\"").arg(updateGroupMask).arg(id).arg(updateUserName);
  query.exec(command);
  root->friendsManager->updateUserGroupEnd();
}

void Server::addContentFilter(QString groupName, int bit)
{
  QSqlQuery query;
  QString command;

  int sortorder = 50;
  command = QString("insert into groups (users_id, name, bit, sortorder, type) values (%1, \"%2\", %3, %4, 0)").arg(id).arg(groupName).arg(bit).arg(sortorder);
  query.exec(command);
  updateGroupId = bit;
}

void Server::addUserContentFilter(QString userName, int bit)
{
  QSqlQuery query;
  QString command;

  command = QString("select data from groups where users_id=%1 and bit=%2").arg(id).arg(bit);
  query.exec(command);
  if (!query.next()) return; // no such filter - shouldn't happen
  QString data = query.value(0).toString();
  data.append(" ");
  data.append(userName);
  command = QString("update groups set data=\"%1\" where users_id=%2 and bit=%3").arg(data).arg(id).arg(bit);
  query.exec(command);

  root->friendsManager->updateUserGroupEnd();
}

void Server::deleteUserContentFilter(QString userName, int bit)
{
  QSqlQuery query;
  QString command;

  command = QString("select data from groups where users_id=%1 and bit=%2").arg(id).arg(bit);
  query.exec(command);
  if (!query.next()) return; // no such filter - shouldn't happen
  QString data = query.value(0).toString();
  data.replace(userName," ");

  command = QString("update groups set data=\"%1\" where users_id=%2 and bit=%3").arg(data).arg(id).arg(bit);
  query.exec(command);

  root->friendsManager->updateUserGroupEnd();
}




void Server::addUser(QString userName, QString fullName)
{
  QSqlQuery query;
  QString command;

  // updating multiple users with colors is currently not supported
  // so if colors are set, it's only one user
  QString foreground = "";
  QString background = "";
  if (updateForeground != "") {
    foreground = QString(", fgcolor=\"%1\" ").arg(updateForeground);
  }
  if (updateBackground != "") {
    background = QString(", bgcolor=\"%1\" ").arg(updateBackground);
  }

  int trust = 1; // for LJ, adding a friend is equivalent to DW set trust+watch
  command = QString("select username from friends where users_id=%1 and username=\"%2\"").arg(id).arg(userName);
  query.exec(command);
  if (query.next()) {
    command = QString("update friends set trust=%1 %2 %3 where users_id=%4 and username=\"%5\"").arg(trust).arg(foreground).arg(background).arg(id).arg(userName);
  }
  else {
    command = QString("insert into friends (users_id, username, fullname, trust, type) values (%1, \"%2\", \"%3\", \"%4\", 0)").arg(id).arg(userName).arg(fullName).arg(trust);
  }
  query.exec(command);
}

void Server::addUserDw(QString userName, QString fullName, int trust, int watch, int trusted, int watched)
{
  QSqlQuery query;
  QString command;

  // updating multiple users with colors is currently not supported
  // so if colors are set, it's only one user
  QString foreground = "";
  QString background = "";
  if (updateForeground != "") {
    foreground = QString(", fgcolor=\"%1\" ").arg(updateForeground);
  }
  if (updateBackground != "") {
    background = QString(", bgcolor=\"%1\" ").arg(updateBackground);
  }

  command = QString("select username from friends where users_id=%1 and username=\"%2\"").arg(id).arg(userName);
  query.exec(command);
  if (query.next()) {
    command = QString("update friends set trust=%1, watch=%2, trusted=%3, watched=%4 %5 %6 where users_id=%7 and username=\"%8\"").arg(trust).arg(watch).arg(trusted).arg(watched).arg(foreground).arg(background).arg(id).arg(userName);
  }
  else {
    command = QString("insert into friends (users_id, username, fullname, trust, watch, trusted, watched, type) values (%1, \"%2\", \"%3\", %4, %5, %6, %7, 0)").arg(id).arg(userName).arg(fullName).arg(trust).arg(watch).arg(trusted).arg(watched);
  }
  query.exec(command);
}
